#include "StdAfx.h"
#include <windows.h>
#include <RichEdit.h>
#include <Oleidl.h>
#include <Richole.h>
#include <assert.h>
#include <commctrl.h>
#include <sstream>

#include "RichEdit.h"

using namespace std;




CRichEdit::CRichEdit(HWND hParent, HINSTANCE hInstance, bool bReadOnly /* = true */) : m_bReadOnly(bReadOnly), m_pRichEditOle(0)
{
	HMODULE hRichEdit = LoadLibrary(L"Msftedit.dll");
	m_hEditWnd = CreateWindow(MSFTEDIT_CLASS, NULL, WS_CHILD| WS_CLIPSIBLINGS | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | ES_LEFT | ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL |
		(bReadOnly ? ES_READONLY : 0), 0, 0, 0, 0, hParent, (HMENU)ID_EDIT, hInstance, NULL);

	

}


CRichEdit::~CRichEdit(void)
{
}


void CRichEdit::AppendText(const std::wstring &text)
{
	int lineCount = (int)SendMessage(m_hEditWnd, EM_GETLINECOUNT, 0, 0);
	wstring currentText = GetText(); 
	
	if (currentText.empty())
	{
		SetWindowText(m_hEditWnd, text.c_str());
	}
	else
	{
		currentText += text;
		::SendMessage(m_hEditWnd, EM_SETSEL, 0, -1);
		DWORD dwStart, dwEnd;
		::SendMessage(m_hEditWnd, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd);
		::SendMessage(m_hEditWnd, EM_SETSEL, dwEnd+1, dwEnd+1); 
		::SendMessage(m_hEditWnd, EM_REPLACESEL, (WPARAM)TRUE, (LPARAM)text.c_str());
		//SetWindowText(m_hEditWnd, currentText.c_str());
	}

	int newLineCount = (int)SendMessage(m_hEditWnd, EM_GETLINECOUNT, 0, 0);

	for (;lineCount < newLineCount; ++lineCount)
		SendMessage(m_hEditWnd, EM_SCROLL, SB_LINEDOWN, 0);
	
	SendMessage(m_hEditWnd, EM_SCROLL, SB_PAGEDOWN, 0);
	SendMessage(m_hEditWnd, EM_SCROLL, SB_LINEUP, 0);
	
}

void CRichEdit::Clear()
{
	SetWindowText(m_hEditWnd, L"");
}

wstring CRichEdit::GetText() const
{
	int textLength = GetWindowTextLength(m_hEditWnd);
	wchar_t *buffer = new wchar_t[textLength + 1];
	GetWindowText(m_hEditWnd, buffer, textLength + 1);
	wstring text(buffer);
	delete buffer;
	return text;
}

void CRichEdit::Copy()
{
	SendMessage(m_hEditWnd, WM_COPY, 0, 0);
}

void CRichEdit::SetSize(const RECT &rect)
{
	MoveWindow(m_hEditWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE);
}

void CRichEdit::PopulateRangeOfLine(int line, CHARRANGE &charRange) const
{
	const wstring &currentText = GetText();
	charRange.cpMin = charRange.cpMax = 0;

	basic_stringstream<wchar_t> text((wchar_t *)currentText.c_str());

	wstring textLine;

	while (getline(text, textLine))
	{
		if (--line <  0)
			break;
		charRange.cpMin = charRange.cpMax;
		charRange.cpMax += (LONG)textLine.length();
	}
}


void CRichEdit::SetLineColor(int line, COLORREF color)
{
	CHARRANGE charRange;
	PopulateRangeOfLine(line, charRange);
	SendMessage(m_hEditWnd,  EM_EXSETSEL, 0, (LPARAM)&charRange);
	CHARFORMAT charFormat = {sizeof(CHARFORMAT) };
	charFormat.crTextColor = color;
	charFormat.dwMask = CFM_COLOR;
	SendMessage(m_hEditWnd, EM_SETCHARFORMAT , (WPARAM)SCF_SELECTION, (LPARAM)&charFormat);
}
void CRichEdit::InsertBitmap(HBITMAP hBitmap)
{
	if (m_pRichEditOle == 0)
	{
		//Cache the richedit ole interface
		::SendMessage((HWND)m_hEditWnd, EM_GETOLEINTERFACE, 0,
			(LPARAM)&m_pRichEditOle);

	}
	
	::SendMessage(m_hEditWnd, EM_SETSEL, 0, -1);
	DWORD dwStart, dwEnd;
	::SendMessage(m_hEditWnd, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd);
	::SendMessage(m_hEditWnd, EM_SETSEL, dwEnd+1, dwEnd+1); 

	CImageDataObject::InsertBitmap(m_pRichEditOle, hBitmap);

	::SendMessage(m_hEditWnd, EM_SCROLLCARET, (WPARAM)0, (LPARAM)0); 
}

	
//
//void CRichEdit::SetLineBackgroundColor()
//{
//
//}